<template>
  <div class="process-container">
    <a-card>
      <div class="table-header">
        <div class="table-title">进程</div>
      </div>
      <a-table
        :columns="columns"
        :data-source="processList"
        :loading="loading"
        row-key="pid"
        bordered
        size="middle"
        :pagination="false"
        :scroll="{ y: 'calc(100vh - 280px)', x: '1200px' }"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'action'">
            <a @click="showDetail(record)">查看详情</a>
            <a-divider type="vertical" />
            <a @click="endProcess(record)" style="color: #ff4d4f;">结束</a>
          </template>
          <template v-else-if="column.key === 'cpuPercent'">
            <div>
              {{ record.cpuPercent }}%
              <a-progress 
                :percent="record.cpuPercent" 
                :stroke-color="getColorByCPU(record.cpuPercent)"
                :show-info="false"
                size="small"
                style="width: 80px; display: inline-block; margin-left: 8px;"
              />
            </div>
          </template>
          <template v-else-if="column.key === 'memoryPercent'">
            <div>
              {{ formatBytes(record.memoryUsage) }}
              <a-progress 
                :percent="record.memoryPercent * 100" 
                :stroke-color="getColorByMemory(record.memoryPercent * 100)"
                :show-info="false"
                size="small"
                style="width: 80px; display: inline-block; margin-left: 8px;"
              />
            </div>
          </template>
          <template v-else-if="column.key === 'port'">
            <template v-if="record.port && record.port.length">
              <a-tag v-for="port in record.port" :key="port" color="blue">{{ port }}</a-tag>
            </template>
            <template v-else>-</template>
          </template>
        </template>
      </a-table>
    </a-card>
    <!-- 详情弹窗 -->
    <a-modal v-model:open="detailVisible" title="进程详情" :footer="null" width="700px">
      <a-descriptions bordered :column="2" size="middle">
        <a-descriptions-item label="名称">{{ detailData.name }}</a-descriptions-item>
        <a-descriptions-item label="状态">{{ detailData.status }}</a-descriptions-item>
        <a-descriptions-item label="进程ID">{{ detailData.pid }}</a-descriptions-item>
        <a-descriptions-item label="父进程ID">{{ detailData.ppid }}</a-descriptions-item>
        <a-descriptions-item label="线程数">{{ detailData.threads }}</a-descriptions-item>
        <a-descriptions-item label="CPU使用率">{{ detailData.cpuPercent }}%</a-descriptions-item>
        <a-descriptions-item label="内存使用率">{{ detailData.memoryPercent ? (detailData.memoryPercent * 100).toFixed(2) + '%' : '0%' }}</a-descriptions-item>
        <a-descriptions-item label="内存使用量">{{ formatBytes(detailData.memoryUsage) }}</a-descriptions-item>
        <a-descriptions-item label="用户">{{ detailData.user }}</a-descriptions-item>
        <a-descriptions-item label="优先级">{{ detailData.nice || '-' }}</a-descriptions-item>
        <a-descriptions-item label="启动时间">{{ detailData.startTime }}</a-descriptions-item>
        <a-descriptions-item label="运行时间">{{ detailData.runTime }}</a-descriptions-item>
        <a-descriptions-item label="监听端口" :span="2">
          <template v-if="detailData.port && detailData.port.length">
            <a-tag v-for="port in detailData.port" :key="port" color="blue">{{ port }}</a-tag>
          </template>
          <template v-else>-</template>
        </a-descriptions-item>
        <a-descriptions-item label="可执行文件路径" :span="2">{{ detailData.exePath || '-' }}</a-descriptions-item>
        <a-descriptions-item label="命令行" :span="2">{{ detailData.commandLine || '-' }}</a-descriptions-item>
      </a-descriptions>
    </a-modal>
    
    <!-- 自定义消息提示区域 -->
    <div class="process-messages" v-if="processMessages.length">
      <transition-group name="message-fade">
        <div v-for="msg in processMessages" :key="msg.id" :class="['process-message', `process-message-${msg.type}`]">
          <span class="message-content">{{ msg.content }}</span>
        </div>
      </transition-group>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { killProcess } from '@/api/index.js'
import { message } from 'ant-design-vue'

const loading = ref(false)
const processList = ref([])
const detailVisible = ref(false)
const detailData = ref({})
let ws = null
let reconnectTimer = null
// 页面级消息管理
const processMessages = ref([])
let messageIdCounter = 0

const columns = [
  { title: 'PID', dataIndex: 'pid', key: 'pid', width: 80, sorter: (a, b) => a.pid - b.pid },
  { title: '名称', dataIndex: 'name', key: 'name', width: 120 },
  { title: '状态', dataIndex: 'status', key: 'status', width: 100 },
  { title: 'CPU', dataIndex: 'cpuPercent', key: 'cpuPercent', width: 150, sorter: (a, b) => a.cpuPercent - b.cpuPercent },
  { title: '内存', dataIndex: 'memoryUsage', key: 'memoryPercent', width: 150, sorter: (a, b) => a.memoryUsage - b.memoryUsage },
  { title: '父进程ID', dataIndex: 'ppid', key: 'ppid', width: 100 },
  { title: '用户', dataIndex: 'user', key: 'user', width: 120, ellipsis: true },
  { title: '线程数', dataIndex: 'threads', key: 'threads', width: 80 },
  { title: '端口', dataIndex: 'port', key: 'port', width: 120 },
  { title: '启动时间', dataIndex: 'startTime', key: 'startTime', width: 150, sorter: (a, b) => new Date(a.startTime) - new Date(b.startTime) },
  { title: '运行时间', dataIndex: 'runTime', key: 'runTime', width: 120 },
  { title: '操作', key: 'action', fixed: 'right', width: 120 }
]

// 格式化字节数为易读形式
const formatBytes = (bytes, decimals = 2) => {
  if (bytes === 0 || bytes === undefined || bytes === null) return '0 B'
  
  const k = 1024
  const dm = decimals < 0 ? 0 : decimals
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
  
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  
  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
}

// 根据CPU使用率获取颜色
const getColorByCPU = (value) => {
  if (value >= 90) return '#f5222d'
  if (value >= 70) return '#fa8c16'
  if (value >= 50) return '#faad14'
  return '#52c41a'
}

// 根据内存使用率获取颜色
const getColorByMemory = (value) => {
  if (value >= 90) return '#f5222d'
  if (value >= 70) return '#fa8c16'
  if (value >= 50) return '#faad14'
  return '#52c41a'
}

// 页面级消息系统
const showPageMessage = (content, type = 'info', duration = 3000) => {
  const id = messageIdCounter++
  const msg = { id, content, type }
  processMessages.value.push(msg)
  
  // 自动移除消息
  setTimeout(() => {
    const index = processMessages.value.findIndex(m => m.id === id)
    if (index !== -1) {
      processMessages.value.splice(index, 1)
    }
  }, duration)
  
  return id
}

function connectWebSocket() {
  ws = new WebSocket('ws://localhost:8000/api/process/ws')
  loading.value = true
  ws.onopen = () => {
    loading.value = false
    showPageMessage('进程数据连接已建立', 'success')
  }
  ws.onmessage = (event) => {
    try {
      const data = JSON.parse(event.data)
      if (data && data.processes && Array.isArray(data.processes)) {
        processList.value = data.processes
      } else if (Array.isArray(data)) {
        processList.value = data
      }
    } catch (e) {
      console.error('进程数据解析失败', e)
      showPageMessage('进程数据解析失败', 'error')
    }
  }
  ws.onerror = () => {
    loading.value = false
    showPageMessage('WebSocket 连接出错', 'error')
    reconnect()
  }
  ws.onclose = () => {
    loading.value = false
    showPageMessage('WebSocket 连接已断开，正在重连...', 'warning')
    reconnect()
  }
}

function reconnect() {
  if (reconnectTimer) clearTimeout(reconnectTimer)
  reconnectTimer = setTimeout(() => {
    connectWebSocket()
  }, 2000)
}


const showDetail = (record) => {
  detailData.value = record
  detailVisible.value = true
}

const endProcess = async (record) => {
  try {
    await killProcess(record.pid)
    showPageMessage(`进程 ${record.name}(${record.pid}) 已结束`, 'success')
    // WebSocket会自动推送最新数据，无需手动刷新
  } catch (e) {
    showPageMessage('结束进程失败', 'error')
  }
}

onMounted(() => {
  connectWebSocket()
})
onUnmounted(() => {
  if (ws) ws.close()
  if (reconnectTimer) clearTimeout(reconnectTimer)
})
</script>

<style scoped>
.process-container {
  padding: 24px;
  height: calc(100vh - 48px); /* 减去上下内边距 */
  overflow: hidden;
  display: flex;
  flex-direction: column;
  position: relative;
}

.table-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.table-title {
  font-size: 18px;
  font-weight: bold;
  flex-shrink: 0;
}

:deep(.ant-card) {
  flex: 1;
  display: flex;
  flex-direction: column;
  margin-bottom: 0;
}

:deep(.ant-card-body) {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 16px;
  overflow: hidden;
}

:deep(.ant-table-wrapper) {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: visible; /* 允许内容可见 */
}

:deep(.ant-spin-nested-loading) {
  flex: 1;
  display: flex;
  flex-direction: column;
}

:deep(.ant-spin-container) {
  flex: 1;
  display: flex;
  flex-direction: column;
}

:deep(.ant-table) {
  flex: 1;
  display: flex;
  flex-direction: column;
}

:deep(.ant-table-container) {
  flex: 1;
  display: flex;
  flex-direction: column;
}

:deep(.ant-table-content) {
  flex: 1;
}

:deep(.ant-table-body) {
  overflow-y: auto !important; /* 强制启用垂直滚动 */
  height: auto !important; /* 自动高度 */
  max-height: calc(100vh - 180px) !important; /* 限制最大高度，保留足够空间 */
}

/* 滚动条样式 */
:deep(.ant-table-body::-webkit-scrollbar) {
  width: 8px;
  height: 8px;
}

:deep(.ant-table-body::-webkit-scrollbar-thumb) {
  background: #c1c1c1;
  border-radius: 4px;
}

:deep(.ant-table-body::-webkit-scrollbar-track) {
  background: #f0f0f0;
}

:deep(.ant-table-tbody > tr:last-child > td) {
  padding-bottom: 16px; /* 确保最后一行有足够的底部空间 */
}

:deep(.ant-tag) {
  margin: 2px;
}

:deep(.ant-descriptions-item-label) {
  width: 100px;
  font-weight: 500;
}

/* 页面级消息样式 */
.process-messages {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.process-message {
  padding: 8px 16px;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  animation: slide-in 0.3s ease;
  min-width: 200px;
}

.process-message-info {
  background-color: #e6f7ff;
  border: 1px solid #91d5ff;
}

.process-message-success {
  background-color: #f6ffed;
  border: 1px solid #b7eb8f;
}

.process-message-warning {
  background-color: #fffbe6;
  border: 1px solid #ffe58f;
}

.process-message-error {
  background-color: #fff2f0;
  border: 1px solid #ffccc7;
}

.message-fade-enter-active,
.message-fade-leave-active {
  transition: opacity 0.3s, transform 0.3s;
}

.message-fade-enter-from,
.message-fade-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

@keyframes slide-in {
  from {
    transform: translateX(30px);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}
</style>